﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Printing;
using WMS.HelperClasses;
using WHMS.EntityClasses;
using SD.LLBLGen.Pro.ORMSupportClasses;
using WHMS.HelperClasses;

namespace WMS
{
    public partial class BarCodeGenerator : Form
    {
        private BarcodeLib.Barcode _barCode;
        private PrintDocument _printBarCodeDocument;
        private string _generatedBarCode;
        private string _workingItemCode;

        private enum ProductType {Product, Shelf}

        public BarCodeGenerator()
        {
            InitializeComponent();

            _barCode = new BarcodeLib.Barcode();

            _printBarCodeDocument = new PrintDocument();
            _printBarCodeDocument.PrintPage += (OnPrintBarCodeDocumentPrintPage);

            txtWidth.Text = @"300";
            txtHeight.Text = @"150";
        }

        private void BtnGenerateBarCodeClick(object sender, EventArgs e)
        {
            int width;
            int height;
            ProductType productType = new ProductType(); ;

            if (!int.TryParse(this.txtWidth.Text.Trim(), out width) ||
                !int.TryParse(this.txtHeight.Text.Trim(), out height))
            {
                MessageBox.Show(@"من فضلك أدخل قيماً صحيحة للطول او العرض");
                return;
            }

            // I used this type as it is like our barcode in Egypt and used widely for retailing
            BarcodeLib.TYPE barcodeType = BarcodeLib.TYPE.CODE128;

            try
            {
                _barCode.IncludeLabel = true;

                

                //the following boolean indicate if the barcode of item/shelf is generated before or not
                bool barCodeGeneratedBefore=false;


                //===== Encoding is performed here =====
                if (rbActivateItemCode.Checked)
                {
                    string itemBarCode = null;
                    string itemOriginalBarCode = null;
                    _workingItemCode = this.txtItemCode.Text.Trim();
                    
                    DataTable itemDT = Business.GetItemDetails(_workingItemCode);
                    if (itemDT.Rows.Count <= 0)
                    {
                        MessageBox.Show(@"هذا الكود غير موجود");
                        return;
                    }

                     itemBarCode=itemDT.Rows[0][3].ToString();
                     itemOriginalBarCode=itemDT.Rows[0][4].ToString();

                    if(!(String.IsNullOrEmpty(itemOriginalBarCode)) ||!(String.IsNullOrEmpty(itemBarCode) ))
                    {
                        barCodeGeneratedBefore = true;
                        _generatedBarCode = String.IsNullOrEmpty(itemBarCode) ? itemOriginalBarCode : itemBarCode;
                    }

                    productType = ProductType.Product;
                }
                else if(rbActivateShelfCode.Checked)
                {
                    string shelfBarCode = null;
                    string shelfOriginalBarCode = null;
                    _workingItemCode = this.txtShelfCode.Text.Trim();

                    DataTable ShelfDT = Business.GetShelfDetails(_workingItemCode);

                    if (ShelfDT.Rows.Count <= 0)
                    {
                        MessageBox.Show(@"هذا الكود غير موجود");
                        return;
                    }

                    shelfBarCode = ShelfDT.Rows[0][3].ToString();
                    shelfOriginalBarCode = ShelfDT.Rows[0][4].ToString();

                    if (!(String.IsNullOrEmpty(shelfOriginalBarCode)) || !(String.IsNullOrEmpty(shelfBarCode)))
                    {
                        barCodeGeneratedBefore = true;
                        _generatedBarCode = String.IsNullOrEmpty(shelfBarCode) ? shelfOriginalBarCode : shelfBarCode;
                    }
                    productType = ProductType.Shelf;
                }

                if (!barCodeGeneratedBefore)
                    _generatedBarCode = GenerateStaticBarCode(_workingItemCode,productType);
                else
                {
                    txtGeneratedBarCode.Text = _generatedBarCode;
                    lblErrorMessage.Visible = true;
                    btnSave.Enabled = false;
                }
               
                    
               
                
                pBoxBarCode.Image = _barCode.Encode(barcodeType, _generatedBarCode, this.ForeColor, this.BackColor, width, height);
                

                //===================================

                //===== Static Encoding performed here =====
                //barcode.Image = BarcodeLib.Barcode.DoEncode(type, this.txtData.Text.Trim(), this.btnForeColor.BackColor, this.btnBackColor.BackColor);
                //==========================================

                pBoxBarCode.Width = pBoxBarCode.Image.Width;
                pBoxBarCode.Height = pBoxBarCode.Image.Height;

                //Reposition the barcode image to the middle
                pBoxBarCode.Location = new Point((this.pBoxBarCode.Location.X + this.pBoxBarCode.Width / 2) - pBoxBarCode.Width / 2,
                                             (this.pBoxBarCode.Location.Y + this.pBoxBarCode.Height / 2) - pBoxBarCode.Height / 2);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void BtnPrintClick(object sender, EventArgs e)
        {
            try
            {
                // Declare the PrintDocument object. 
	          PrintDocument docToPrint = new PrintDocument();
              docToPrint.PrintPage += OnPrintBarCodeDocumentPrintPage;

              PrintDialog PrintDialog1 = new PrintDialog();

                // Allow the user to choose the page range he or she would 
                // like to print.
                PrintDialog1.AllowSomePages = true;

                // Show the help button.
                PrintDialog1.ShowHelp = true;

                // Set the Document property to the PrintDocument for  
                // which the PrintPage Event has been handled. To display the 
                // dialog, either this property or the PrinterSettings property  
                // must be set 
                PrintDialog1.Document = docToPrint;

                DialogResult result = PrintDialog1.ShowDialog();

                // If the result is OK then print the document. 
                if (result == DialogResult.OK)
                {
                    docToPrint.Print();
                }

            }

            catch (Exception)
            {
                MessageBox.Show(@"لا يوجد طابعة مثبتة");
            }

        }

        private void OnPrintBarCodeDocumentPrintPage(Object sender, PrintPageEventArgs e)
        {
            e.Graphics.DrawImage(pBoxBarCode.Image, 0, 0);
        }

        private void RbActivateCodeCheckedChanged(object sender, EventArgs e)
        {
            if (rbActivateItemCode.Checked)
            {
                txtItemCode.Enabled = true;
                btnItemSearch.Enabled = true;

                txtShelfCode.Enabled = false;
                btnShelfSearch.Enabled = false;
            }
            else
            {
                txtItemCode.Enabled = false;
                btnItemSearch.Enabled = false;

                txtShelfCode.Enabled = true;
                btnShelfSearch.Enabled = true;
            }
        }

        private void btnSave_MouseHover(object sender, EventArgs e)
        {
            ToolTip tip = new ToolTip();
            tip.Show("سوف يتم الحفظ للباركود الأصلى ان وجد والا سوف يتم حفظ الكود المنشأ", btnSave);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_generatedBarCode) && string.IsNullOrWhiteSpace(txtOriginalBarCode.Text))
            {
                MessageBox.Show(@"يجب انشاء باركود جديد او ادخال باركود خارجي");
                return;
            }


            if (rbActivateItemCode.Checked)
            {
                _workingItemCode = this.txtItemCode.Text.Trim();
                var entity = new ItemEntity();
                
                if (string.IsNullOrEmpty(txtOriginalBarCode.Text))
                {
                    entity.BarCode = _generatedBarCode;
                }
                else
                {
                    entity.OriginalBarCode = txtOriginalBarCode.Text;
                }
                
                DataTable itemDT = Business.GetItemDetails(txtItemCode.Text);
                
                if (itemDT.Rows.Count <= 0)
                {
                    MessageBox.Show(@"هذا الكود غير موجود");
                    return;
                }
                DALHelper.UpdateEntities(entity, new RelationPredicateBucket(ItemFields.Id == itemDT.Rows[0][0].ToString()));
            }
            else
            {
                _workingItemCode = this.txtShelfCode.Text.Trim();
                var entity = new ShelfEntity();

                if(string.IsNullOrEmpty(txtOriginalBarCode.Text))
                {
                    entity.BarCode = _generatedBarCode;
                }
                else
                {
                    entity.OriginalBarCode = txtOriginalBarCode.Text;
                }
                DataTable shelfDT = Business.GetShelfDetails(txtShelfCode.Text);
                if (shelfDT.Rows.Count <= 0)
                {
                    MessageBox.Show("هذا الكود غير موجود");
                    return;
                }
                DALHelper.UpdateEntities(entity, new RelationPredicateBucket(ShelfFields.Id == shelfDT.Rows[0][0].ToString()));
            }
            MessageBox.Show(@"تم الحفظ بنجاح");
        }

        /// <summary>
        /// A method that generates a unique number based on uniqueness of item code or shelf code
        /// </summary>
        /// <param name="itemOrShelfCode"></param>
        /// <returns>13 digits number as normal bar code in Egypt called EAN13</returns>
        [Obsolete]
        private string GenerateBarCode(string itemOrShelfCode,ProductType productType)
        {
            if (string.IsNullOrWhiteSpace(itemOrShelfCode)) throw new Exception("لا يوجد كود مدخل");

            long longValue;
            var workingItem = new StringBuilder(itemOrShelfCode);
            var length = 13 - workingItem.Length;

            if (workingItem.Length < 13)
            {
                var randomNumber = new Random();
                int bytesLength;
                if(length % 2 == 0)
                {
                    bytesLength = length/2;
                }
                else
                {
                    bytesLength = (length + 1)/2;
                }
                var randomBytes = new byte[bytesLength];
                string stringBytes = string.Empty;

                randomNumber.NextBytes(randomBytes);
                foreach (var randomByte in randomBytes)
                {
                    stringBytes += randomByte.ToString();
                }
                workingItem.Insert(0, stringBytes);
            }
            else
            {
                workingItem.Remove(0, (-1 * length));
            }
            string result;
            // if it is a number 
            if (long.TryParse(workingItem.ToString(), out longValue))
            {
                var temp = longValue * 13;
                 result= temp.ToString().Substring(temp.ToString().Length - 13, 13);
                
            }
            else
            {
                byte[] bytes = Encoding.ASCII.GetBytes(workingItem.ToString());
                workingItem.Remove(0, workingItem.Length);

                foreach (byte b in bytes)
                {
                    workingItem.Append(b);
                }

                 result = workingItem.ToString().Substring(workingItem.ToString().Length - 13, 13);
               
                
            }

            if (productType == ProductType.Product)
            {
                result = "111" + result;
            }
            else if (productType == ProductType.Shelf)
            {
                result = "222" + result;
            }

            txtGeneratedBarCode.Text = result;
            return result;
        }

        /// <summary>
        /// A method that generates bar code from static portion + code of shelf or item
        /// </summary>
        /// <param name="itemOrShelfCode"></param>
        /// <param name="productType"></param>
        /// <returns></returns>
        private string GenerateStaticBarCode(string itemOrShelfCode,ProductType productType)
        {
            if (string.IsNullOrWhiteSpace(itemOrShelfCode)) throw new Exception("لا يوجد كود مدخل");

            string result = string.Empty;

            if (productType == ProductType.Product)
            {
                result = "111" + itemOrShelfCode;
            }
            else if (productType == ProductType.Shelf)
            {
                result = "222" + itemOrShelfCode;
            }

            txtGeneratedBarCode.Text = result;
            return result;
        }

        private void btnItemSearch_Click(object sender, EventArgs e)
        {
            var searchForm = new fromGeneralEntityPicker("Item");
            if (searchForm.ShowDialog() == DialogResult.OK)
            {
                txtItemCode.Text = searchForm.SelectedItemCode;

            }
        }

        private void btnSearchStore_Click(object sender, EventArgs e)
        {
            var searchForm = new fromGeneralEntityPicker("Shelf");
            if (searchForm.ShowDialog() == DialogResult.OK)
            {
                txtShelfCode.Text = searchForm.SelectedItemCode;

            }
        }

        private void ResetForm()
        {
            lblProductName.Text = String.Empty;
            txtWidth.Text = @"300";
            txtHeight.Text = @"150";
            txtOriginalBarCode.Text = String.Empty;
            txtGeneratedBarCode.Text = String.Empty;
            pBoxBarCode.Image = null;
            lblErrorMessage.Visible = false;
            btnSave.Enabled = true;
        }
        private void txtItemCode_TextChanged(object sender, EventArgs e)
        {
            ResetForm();

            if (!String.IsNullOrEmpty(txtItemCode.Text))
            {
                DataTable DTProduct = Business.GetItemDetails(txtItemCode.Text);
                if (DTProduct.Rows.Count > 0)
                {
                    //selectedProductID = Int32.Parse(DTProduct.Rows[0][0].ToString());
                    lblProductName.Text = DTProduct.Rows[0][1].ToString();
                    
                }
                else
                {
                    lblProductName.Text = string.Empty;
                    
                }
            }
        }

        private void btnShelfSearch_Click(object sender, EventArgs e)
        {
            var filter = new RelationPredicateBucket();//(StorekeeperFields.KeeperId == Business.GetCurrentUserId());
            filter.Relations.Add(ShelfEntity.Relations.StoreEntityUsingStoreId);
            //filter.Relations.Add(TransferRequestEntity.Relations.StoreEntityUsingFromStoreId);
            filter.Relations.Add(StoreEntity.Relations.ShelfEntityUsingStoreId);

            //var searchForm = new SearchForm(TransferRequestFields.RequestNumber, TransferRequestFields.ProjectId, TransferRequestFields.Date, filter, () => Business.GetRunningProjects());




            var searchShelfForm = new SearchShelfForm(ShelfFields.Code, ShelfFields.StoreId, filter, () => Business.GetStoreDetails(null));
            if (searchShelfForm.ShowDialog() == DialogResult.OK)
            {
                txtShelfCode.Text = searchShelfForm.SelectedShelfCode;

            }
        }

        private void txtShelfCode_TextChanged(object sender, EventArgs e)
        {
            ResetForm();
        }
    }
}
